import 'package:expensy_flutter/_inner_packages.dart';
import 'package:expensy_flutter/_external_packages.dart';
import 'package:expensy_flutter/models/_models.dart';
import 'package:expensy_flutter/helpers/_helpers.dart';

class TransactionsData with ChangeNotifier {
  final int _maxAmountDummyData = 32;
  List<MonetaryTransaction> _transactions = [];
  DBHelper dbHelper;
  TransactionsData() {
    dbHelper = DBHelper();
    refreshTransactionList();
  }

  get transactions {
    return _transactions;
  }

  get lastWeekTransactions {
    final DateTime now = DateTime.now();
    return _transactions.where((transaction) {
      int daysAgo = now.difference(transaction.executionDate).inDays;
      return (daysAgo <= 6 && daysAgo >= 0);
    }).toList();
  }

  void _generateDummyData() async {
    final List<MonetaryTransaction> monetaryTransactions =
        await dbHelper.getMonetaryTransactions();
    final int currentLength = monetaryTransactions.length;
    if (currentLength < _maxAmountDummyData) {
      for (int i = 0; i < (_maxAmountDummyData - currentLength); i++) {
        String title = faker.food.dish();
        double amount = NumericHelper.roundRandomDoubleInRange(
            min: 0.99, max: 10.00, places: 2);
        DateTime executionDate = DateHelper.randomDateTimeOnTheLastWeek();
        await addTransaction(title, amount, executionDate);
      }
    }
  }

  void _removeTransactionWhere(int id) async {
    await dbHelper.deleteTransaction(id);
    await refreshTransactionList();
  }

  Future refreshTransactionList() async {
    _transactions = await dbHelper.getMonetaryTransactions();
    notifyListeners();
  }

  Future<void> _showDialogPlus(int id, BuildContext context) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('确定删除该记录?'),
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12.0)), //this right here
          content: SingleChildScrollView(
            child: Container(
              padding: EdgeInsets.all(12),
              child: Column(
                children: <Widget>[
                  Text(
                    '此操作不可恢复.',
                    style: TextStyle(
                      color: Theme.of(context).errorColor,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
          ),
          actions: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ElevatedButton(
                child: Row(
                  children: [
                    Text('取消'),
                    SizedBox(
                      width: 10,
                    ),
                    Icon(Icons.cancel),
                  ],
                ),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: ElevatedButton(
                child: Row(
                  children: [
                    Text('确定'),
                    SizedBox(
                      width: 10,
                    ),
                    Icon(Icons.delete),
                  ],
                ),
                onPressed: () {
                  deleteTransactionWithoutConfirm(id);
                  Navigator.of(context).pop();
                },
              ),
            ),
          ],
        );
      },
    );
  }

  Alert createAlert({int id, BuildContext context, String message = ''}) {
    return Alert(
      context: context,
      type: AlertType.warning,
      title: "确定?",
      // desc: message,
      buttons: [
        DialogButton(
          child: Text(
            "确定",
            style: TextStyle(color: Colors.white, fontSize: 20),
          ),
          onPressed: () {
            _removeTransactionWhere(id);
            Navigator.of(context).pop();
          },
          width: 120,
        ),
        DialogButton(
          child: Text(
            "取消",
            style: TextStyle(color: Colors.white, fontSize: 20),
          ),
          onPressed: () => Navigator.pop(context),
          width: 120,
        ),
      ],
    );
  }

  Future<void> addTransaction(
      String title, double amount, DateTime executionDate) async {
    DateTime now = DateTime.now();
    MonetaryTransaction newTransaction = MonetaryTransaction(
      title: title,
      amount: amount,
      executionDate: executionDate,
      createdAt: now,
      updatedAt: now,
    );

    await dbHelper.saveTransaction(newTransaction);
    refreshTransactionList();
  }

  Future<void> updateTransaction(
      int id, String title, double amount, DateTime executionDate) async {
    DateTime now = DateTime.now();
    MonetaryTransaction updatingTransaction =
        _transactions.firstWhere((transaction) => id == transaction.id);

    updatingTransaction.title = title;
    updatingTransaction.amount = amount;
    updatingTransaction.executionDate = executionDate;
    updatingTransaction.updatedAt = now;

    await dbHelper.updateTransaction(updatingTransaction);
    refreshTransactionList();
  }

  Future<void> deleteTransactionWithConfirm(int id, BuildContext context) {
    _showDialogPlus(id, context).then((value) {
      (context as Element).reassemble();
      refreshTransactionList();
    });
  }

  void deleteTransactionWithoutConfirm(int id) {
    _removeTransactionWhere(id);
    refreshTransactionList();
  }

  List<Map> groupedAmountLastWeek() {
    List<double> lastWeekAmounts = this.lastWeekAmounts();

    return List.generate(7, (index) {
      return {
        'day': DateHelper.weekDayTimeAgo(days: index),
        'amount': lastWeekAmounts[index],
      };
    });
  }

  double biggestAmountLastWeek() {
    return NumericHelper.biggestDoubleFromList(lastWeekAmounts());
  }

  List<double> lastWeekAmounts() {
    final DateTime now = DateTime.now();
    List<double> result = [0, 0, 0, 0, 0, 0, 0];

    lastWeekTransactions.forEach((transaction) {
      int daysAgo = now.difference(transaction.executionDate).inDays;
      result[daysAgo] += transaction.amount;
    });

    return NumericHelper.roundDoubles(result, 2);
  }
}
